iT邦幫忙

2024 iThome 鐵人賽

DAY 1
0

嗨~大家好,我是Rafael,從原本的農業領域轉職剛滿1年,目前在AI數據公司擔任前端工程師。

最近自己籌組的Vue3線上讀書會順利結束了🥳,也剛好是以Vue3開發快近1年時間,想說整理自己撰寫的Vue讀書會綱要,並將各主題再深入探討撰寫成文章,會想發起這個心願主要一直心中有個原因:

Vue的官網其實對使用者滿好上手的,正因為如此,許多開發上細節或和正確觀念我們不得而知。也就造成許多初學開發者(包括本人),知其然而不知其所以然,亂用產生bug而不得其解的情況出現。

大概會以官網一些基本介紹為基底,加入額外文章資源,也會嘗試加入一些SOLID設計準則,希望形成一些火花看看,第一次參加鐵人賽,也希望大家閱讀時能夠給予回饋,教學相長。


目錄

30天內容,其中會不時穿插一些JavaScript當作複習並和Vue的相關主題作連結:

天數 主題名稱 摘要
1 Vue Create App and Mount 認識Vue的編譯和運行核心模組
2 Vue SFC樣板和渲染函式 渲染函式和虛擬DOM之間的關係
3 script setup語法糖的本質 <script setup> 解決Vue的那些問題?
4 JavaScript常見的物件操作方式 JavaScript物件如何創建、定義屬性和複製?
5 JavaScript代理物件和Reactive Vue響應式基礎-ReactiveProxy 的關係
6 響應式系統-Ref ref 使用時為什麼總是要加.value?
7 計算屬性-Computed computed 的設計核心思想和基本特性
8 Vue的監聽器-watch和watchEffect 理解Vue監聽器基本使用- 深層監聽設定等
9 Vue監聽器的執行時機點 Vue 監聽器執行函式副作用的時機點
10 JavaScript事件循環、宏任務和微任務 理解事件循環(Event Loop)核心觀念
11 Vue的nextTick-DOM更新後的回調 理解nextTick的作用和執行時機點
12 Vue 監聽器副作用的清除 認識watch 回調函式中 onCleanUp的功能
13 Vue元件的事件emits和參數props傳遞 Vue - Props down, events up 原則
14 Vue元件props和響應式資料的驗證 defineProps 驗證功能和製作型別檢查器
15 Vue-插槽(slot)的認識 slot 插槽認識、元件 render scope 觀念
16 無渲染元件-slot props另一種用法 理解無渲染元件和實作
17 v-for指令渲染和使用上的陷阱 v-for 使用注意事項
18 JavaScript工廠函式 vs 類別認識 認識 JavaScript 類別建構子和工廠函式的差別
19 Vue-組合式函式(composable) 理解Composable和一般JavaScript通用函式差別
20 依賴注入模式-Provide and Inject 理解Vue provide inject 和正確使用模式
21 SOLID-單一職責(SRP) 認識單一職責和實作
22 SOLID-開放封閉原則(OCP) 認識開放封閉原則和實作
23 SOLID-里氏替換原則(LSP) 認識替換原則和實作
24 SOLID-介面分離原則(ISP) 認識介面分離原則和實作
25 SOLID-依賴反轉原則(DIP) 認識依賴反轉原則和實作
26 JavaScript和Vue的元件錯誤處理 try/catch/finally 語法和Vue的元件錯誤捕捉
27 JavaScript模組(module)和程式碼分割 理解認識JavaScript模組(module) 和 動態載入
28 Vue 的元件更新優化-重新渲染問題 理解 props stable 概念和重新渲染問題
29 Vue 的不同渲染模式-CSR、SSR和通用渲染模式 理解不同渲染模式、SSR初步注意事項
30 總結-回顧30天的學習心路歷程 總結學習旅程和如何突破困難

那麼就開始Vue的自我探索旅程囉~Go

今日學習重點:

  1. 如何創建Vue應用實例-Vue Create App 和App.mount
  2. Vue package-compiler vs runtime core 到底是什麼?

Create App 做了什麼事

在我們安裝完vue後,打開main.js檔案中應該會出現以下段落程式碼:

import { createApp } from 'vue'
// import the root component App from a single-file component.
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

Vue 其實是一個大型應用專案框架包(package),裡面包含很多應用模組(module), createApp 是 Vue中的一個模組功能,引入後呼叫它並掛載入App.vue這個頂層的vue組件。

createApp 是用來創建 Vue 應用實例的 API。透過 createApp 可以生成一個新的 Vue 應用實例,並掛載根組件(通常是 App.vue),作為應用的入口點。這樣 Vue 就可以開始追蹤資料狀態變化並自動更新畫面。

一個Vue專案結構如下,我們在component 資料夾底下,可包含更多Vue子元件進行開發形成下列結構:

App (root component)
├─ TodoList
│  └─ TodoItem
│     ├─ TodoDeleteButton
│     └─ TodoEditButton
└─ TodoFooter
   ├─ TodoClearButton
   └─ TodoStatistics

App.mount 做了什麼事

mount顧名思義掛載的意思,當然其中有一些非原生JS語言的檔案.vue需要編譯細節不在此階段討論,不過mount功能主要是負責將Vue.js所產生的JS程式碼,調用瀏覽器原生API(例如 document.querySelector、appendChild 等)去掛載或更新真正的DOM元素,達成瀏覽器畫面更新。

在Vue專案中,應該會有一份index.html,裡面是實際瀏覽器運行時需要的html內容,在中通常會以id=app的元素為容器,讓Vue可以知道要截取哪一段html元素。

app.mount(),括號中參數可以是一個 DOM 元素或一个 CSS 選擇器,傳入後Vue會一併返回成為根组件實例的一部分。

瀏覽器上運行Vue 的核心代碼(run-time code)時:

Vue 會將剛剛傳入的容器元素(例如 id="app" 的 )的 innerHTML 作為模板。Vue 會透過 JavaScript 解析器解析這些模板,將它們編譯為虛擬 DOM(Virtual DOM),然後將虛擬 DOM 渲染為實際的 DOM 元素。

最後,Vue 將模板中的內容替換為實際的組件內容,並完成最終的畫面更新。

// index.html
<div id="app"></div>
// main.js
app.mount('#app')

一個Vue app實例,僅能調用一次mount方法

掛載vue實例後vue還需要負責管理组件的生命周期、狀態和響應數據更新。如果多次調用 mount的可能造成不可預期的交互混亂 。

大意是說你不能讓一個Vue instance 掛載多次,因為後續會牽涉到資料流問題,一個實例裡包含許多彼此間不相關的資料狀態,總是有互相影響風險存在。

多頁式應用(Multiple Page Application. MPA)

雖然說Vue 主要是以單頁式應用(Single Page Aplication,SPA)作為主要應用,但並不是說不能做成多頁式應用(Mutiple Page Aplication,MPA),只是需要利用createApp創建多個Vue實例,如同官方所建議的。

MPA專案資料夾

project-root/
├─ public/
│  ├─ index.html
│  ├─ about.html
├─ src/
│  ├─ main.js          // 對應 index.html 的入口文件
│  ├─ about.js         // 對應 about.html 的入口文件
├─ vite.config.js

在不同檔案中創建不同的Vue App 實例

// main.js
const app1 = createApp({
  /* ... */
})
app1.mount('#container-1')

// about.js
const app2 = createApp({
  /* ... */
})
app2.mount('#container-2')

在Vite打包入口檔的設定,可以參考roll up文件
https://cn.rollupjs.org/configuration-options/#input

import { defineConfig } from 'vite';
import { resolve } from 'path';

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'public/index.html'),
        about: resolve(__dirname, 'public/about.html')
      }
    }
  }
});

Vue 的核心組成-compiler vs runtime core

剛剛有稍微提到run-time執行核心,有時候compiler 、 run-time這兩個專有名詞還會掠過耳邊,如果你是剛接觸Vue對它的功能不是很熟悉也沒關係,先理解核心套件會負責那些項目就行,用到再回顧也行。

那麼對vue來說compiler和runtime core這兩個核心主要負責什麼呢?

https://ithelp.ithome.com.tw/upload/images/20240914/20145251oRR32Rcm5z.jpg

在使用上最大的區別:

運行器核心 (Runtime Core):

Runtime Core 是 Vue.js 在瀏覽器中運行的核心部分,其檔案體積較小,專注於運行時的功能。通常指的是通過 Vue CLI 或 Vite 打包後的 JavaScript 檔案,這些檔案在瀏覽器中執行。當我們在網頁上與 Vue 應用互動、觸發資料更新時,Runtime Core 會負責響應式系統、組件渲染和虛擬 DOM 的更新操作,從而實現資料和畫面同步更新。

整理一下對應的Vue功能:

  1. 創建和管理組件銷毀等: 管理組件的生命周期,初始化數據方法等。
  2. 響應式系統(reactive system): 監控數據變化並且能夠自動更新 DOM,也是我們使用框架的核心功能。
  3. 更有效率的DOM 操作: 虛擬DOM(virtual DOM)比對前後更新差異(differ),再去調用負責的DOM API更新畫面(patch)。
    註解:更有效率的DOM操作不代表框架使用遠比使用原生JS DOM操作來的便宜,端看應用規模,Virtual DOM建立和運算也需耗費資源,取決於商業邏輯複雜度相較之下值不值得。

編譯器核心 (Compiler Core):

編譯器核心通常主要負責將模板Vue template編譯成為JS渲染函數render function,可以想像成Vue開發完成後最終需要變成可以執行的第一份JS 程式碼。

我們通常不會在瀏覽器的運行環境中執行模板編譯,因為編譯器檔案體積較大,且在瀏覽器中進行編譯會影響性能。相反地,編譯通常發生在開發或打包過程中。

在開發時環境下我們通常使用 npm run dev(Vite)啟動開發伺服器,本地代碼修改時會觸發熱重載模式(HMR),這會自動重新編譯模板並生成新的 JavaScript 代碼。

而在生產環境中,我們通過執行 npm run build 來打包應用,將模板預編譯為渲染函數,最終生成一份優化過的 JavaScript 文件供瀏覽器運行。

整理一下對應的Vue功能:

  1. template模板解析: vue tempalte模板 透過 AST抽象樹 轉為JS渲染函數render function。

CSS 預處理器

CSS 預處理的過程並不是 Vue 編譯器的職責,而是由構建工具(如 Webpack、Vite)和對應的 Loader(如 sass-loader、less-loader 等)來處理的。

Vue 編譯器主要處理的是 Vue 特有的模板語法,而 CSS 預處理、JavaScript 模組打包等則由構建工具(如 Webpack 或 Vite)負責。構建工具通過配置不同的 Loader 或 Plugin 來處理各種資源文件的編譯和打包。

Webpack 中的 Vue Loader:需要配置 Vue Loader 並安裝相關插件,特別是在使用 CSS 預處理器時,需要相應的 Loader 配置。
Vite 的 Vue 支持:Vite 已經內建對 Vue 的支持,只需簡單配置插件即可。

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()]
});

其實vue源碼專案上也有他開發團隊對Vue的簡介,是採用monorepo形式去開發vue框架的,可以試著打開vue的github稍微理一下,是以上面的runtime core/compiler core 對應職責去做開發和分類。
https://github.com/vuejs/core/blob/v3.0.0-alpha.4/.github/contributing.md#project-structure


總結:

挑了下面這張圖做本次ending,整個Vue學習也是環繞著它,之後也會常常出現。 createApp後到app.mount這中間過程,其實還夾著這張圖一大段流程。

官方是擺在進階的渲染機制(Rendering Mechanism)做介紹,不過本次章節已經有觸碰到App.vue元件檔(template)的掛入,到app.mount -> Actual DOM的一些介紹,算是個開頭,後續進入元件化開發(SFC file component)、響應式資料和虛擬DOM(Virtual DOM)研究囉,希望自己還活著繼續撰寫😆。

https://ithelp.ithome.com.tw/upload/images/20240914/20145251iWlT2xNBlB.png


參考資源:

https://cn.vuejs.org/api/application.html
https://cn.vuejs.org/guide/essentials/application.html
https://medium.com/glovo-engineering/dissecting-vue-3-the-mounting-process-i-32181abf5cc3
(這篇作者很棒,受到他的啟發才有今天的文章整理)


下一篇
Day 2: Vue SFC樣板(Template)和渲染函式(Render Function)
系列文
Vue.js學習中的細節陷阱:30天自我學習指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言